#region Using Statements
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Content;
using Microsoft.Xna.Framework.Graphics;
using Neat;
using Neat.Mathematics;
using Neat.GUI;
using Neat.Graphics;
using Sectors;
using Microsoft.Xna.Framework.Input;
using System;
using System.Diagnostics;
using System.Windows.Forms;
using System.IO;
using System.Collections.Generic;
#endregion

namespace SectorsDesigner
{
    public partial class SectorsMapMakerControl : GraphicsDeviceControl
    {
        public ContentManager Content;
        public new Vector2 MousePosition;
        public MouseButtons MouseButton;
        SpriteBatch spriteBatch;
        public SpriteFont DesignerFont;
        LineBrush lb, tlb;
        Texture2D logo;
        Stopwatch timer;
        Random r = new Random();
        NeatGame n;
        public World World;
        Texture2D crosshair, circle8x8, circle4x4, solid;
        Vector2 crosshairOffset = new Vector2(-8); //performance
        Vector2 circle4x4Offset = new Vector2(-2);
        Vector2 circle8x8Offset = new Vector2(-4);
        Color[] palette;
        Effect ZoomEffect,ColorFilterEffect;
        public bool ShowTriangles = false;
        float ShowSelectedRate = 400.0f;
        Color SelectColor
        {
            get
            {
                return Color.Red;
                //return ((int)(timer.ElapsedMilliseconds/300.0f) % 2 == 0) ? Color.CornflowerBlue : Color.Red;
            }
        }

        bool Clock(float period)
        {
            return ((int)(timer.ElapsedMilliseconds / period)) % 2 == 0;
        }
        public enum EditModes
        {
            NewSector,
            SelectSector,
            SelectEdge,
            SplitEdge,
            SelectVertex
        }
        public enum SectorFillModes
        {
            Wire,
            Solid,
            Floor,
            Ceiling
        }
        public Color SolidFillColor;
        public EditModes EditMode = EditModes.NewSector;
        public SectorFillModes SectorFillMode = SectorFillModes.Wire;

        public Sector SelectedSector;
        public Wall SelectedWall;
        public Vector2 LastVertex;
        public Polygon CurrentPolygon = new Polygon();
        public float CurrentFloor = 0;
        public float CurrentCeiling = 100;
        public float WallSelectRadius = 8; //px
        public bool DoSnapToGrid = true;

        protected override void OnKeyDown(KeyEventArgs e)
        {
            e.Handled = true;
            base.OnKeyDown(e);
        }

        protected override void OnPreviewKeyDown(PreviewKeyDownEventArgs e)
        {
            base.OnPreviewKeyDown(e);
        }
        protected override void Initialize()
        {
            
            n = new NeatGame();
            World = new World();
            LoadContent();
            
            // Start the animation timer.
            timer = Stopwatch.StartNew();

            palette = new Color[256];
            for (int i = 0; i < palette.Length; i++)
            {
                palette[i] = new Color(128 + r.Next(128), 128 + r.Next(128), 128 + r.Next(128));
            }

            Dummy = new MapMaker.Mesh(Edges);
            offset = new Vector2(Width, Height) / 2f;
        }

        void LoadContent()
        {
            Content = new ContentManager(Services, "Content");
            spriteBatch = new SpriteBatch(GraphicsDevice);

            DesignerFont = Content.Load<SpriteFont>("Fonts\\hudFont");
            logo = Content.Load<Texture2D>("Sprites\\sectorslogo");
            ZoomEffect = Content.Load<Effect>("Effects\\DesignerScale");
            ZoomEffect.Parameters["ZoomFactor"].SetValue(2.0f);
            ColorFilterEffect = Content.Load<Effect>("Effects\\ColorFilter");

            InitializeAssets();

            lb = new LineBrush(GraphicsDevice, 1);
            tlb = new LineBrush(GraphicsDevice, 2);
            CreateCrosshair();
            CreateCircle();

            SolidFillColor = Color.White; // GraphicsHelper.GetColorWithAlpha(GraphicsHelper.GetRandomColor(), 0.6f);
            CreateSolid();
            if (File.Exists("textures.lst")) LoadTextureList("textures.lst");
        }

        void CreateSolid()
        {
            solid = new Texture2D(GraphicsDevice, 4, 4);
            Color[] pixmap = new Color[16];
            for (int i = 0; i < 16; i++)
                pixmap[i] = SolidFillColor;
            solid.SetData(pixmap);
        }

        void CreateCrosshair()
        {
            crosshair = new Texture2D(GraphicsDevice, 16, 16);
            Color[] pixmap = new Color[16 * 16];
            for (int i = 0; i < 16; i++)
            {
                pixmap[8 + (i * 16)] = Color.White;
                pixmap[i + (8 * 16)] = Color.White;
            }
            crosshair.SetData(pixmap);
        }

        void CreateCircle()
        {
            var o = Color.Transparent;
            var x = Color.White;
            circle4x4 = new Texture2D(GraphicsDevice, 4, 4);
            circle8x8 = new Texture2D(GraphicsDevice, 8, 8);
            Color[] p4x4 = new Color[4 * 4]{
                o,x,x,o,
                x,x,x,x,
                x,x,x,x,
                o,x,x,o};
            Color[] p8x8 = new Color[8 * 8]{
                o,o,x,x,x,x,o,o,
                o,x,x,x,x,x,x,o,
                x,x,x,x,x,x,x,x,
                x,x,x,x,x,x,x,x,
                x,x,x,x,x,x,x,x,
                x,x,x,x,x,x,x,x,
                o,x,x,x,x,x,x,o,
                o,o,x,x,x,x,o,o};
            circle4x4.SetData(p4x4);
            circle8x8.SetData(p8x8);
        }

        protected override void Dispose(bool disposing)
        {
            if (disposing)
            {
                Content.Unload();
            }

            base.Dispose(disposing);
        }

        public ListBox SectorsListBox = null;
        public ListBox EdgesListBox = null;
        public ListBox VerticesListBox = null;
        public TreeView TreeView = null;
        public Action BeforeRefresh = null;
        public Action AfterRefresh = null;
        public void RefreshListBox()
        {
            if (BeforeRefresh != null) BeforeRefresh();

            if (TreeView != null)
            {
                string selectedKey = null;
                if (TreeView.SelectedNode != null) selectedKey = TreeView.SelectedNode.Name;
                TreeView.Nodes.Clear();

                var sectorsNode = TreeView.Nodes.Add("ps", "Sectors", "sectors", "sectors");
                for (int i = 0; i < this.Sectors.Count; i++)
                {
                    var node = sectorsNode.Nodes.Add("s" + i, this.Sectors[i].Name, "sectors", "sectors");
                    if (selectedKey == node.Name) TreeView.SelectedNode = node;
                }

                var edgesNode = TreeView.Nodes.Add("pe", "Edges", "edges", "edges");
                for (int i = 0; i < this.Edges.Count; i++)
                {
                    if (DeletedEdges.Contains(i)) continue;
                    var node = edgesNode.Nodes.Add("e" + i, this.Edges[i].Wall.Name, "edges", "edges");
                    if (selectedKey == node.Name) TreeView.SelectedNode = node;
                }

                var verticesNode = TreeView.Nodes.Add("pv", "Vertices", "vertices", "vertices");
                for (int i = 0; i < this.Vertices.Count; i++)
                {
                    if (DeletedVertices.Contains(i)) continue;
                    var node = verticesNode.Nodes.Add("v" + i, GeometryHelper.Vector2String(this.Vertices[i]), "vertices", "vertices");
                    if (selectedKey == node.Name) TreeView.SelectedNode = node;
                }

                if (TreeView.SelectedNode != null && TreeView.SelectedNode.Parent != null) TreeView.SelectedNode.Parent.Expand();
            }

            //Sectors
            if (SectorsListBox != null)
            {
                SectorsListBox.Items.Clear();
                int i = 0;
                foreach (var item in this.Sectors)
                {
                    SectorsListBox.Items.Add((++i).ToString() + " - " + item.Name);
                }
                if (CurrentSectorIndex >= 0)
                {
                    foreach (var item in SelectedSectorsIndices)
                    {
                        SectorsListBox.SetSelected(item, true);
                    }
                    //if (SectorsListBox.SelectedIndex != CurrentSectorIndex) 
                    //    SectorsListBox.SelectedIndex = CurrentSectorIndex;
                    SectorsListBox.Refresh();
                }
            }

            //Edges
            if (EdgesListBox != null)
            {
                EdgesListBox.Items.Clear();
                int i = 0;
                foreach (var item in this.Edges)
                {
                    if (DeletedEdges.Contains(i++)) continue;
                    EdgesListBox.Items.Add(i.ToString() + " - " + item.Wall.Name);
                }
                if (CurrentEdgeIndex >= 0)
                {
                    foreach (var item in SelectedEdgesIndices)
                    {
                        EdgesListBox.SetSelected(item, true);
                    }
                    //if (EdgesListBox.SelectedIndex != CurrentEdgeIndex) EdgesListBox.SelectedIndex = CurrentEdgeIndex;
                    EdgesListBox.Refresh();
                }
            }

            //Vertices
            if (VerticesListBox != null)
            {
                VerticesListBox.Items.Clear();
                int i = 0;
                foreach (var item in this.Vertices)
                {
                    if (DeletedVertices.Contains(i++)) continue;
                    VerticesListBox.Items.Add(i.ToString() + " - " + GeometryHelper.Vector2String(item));
                }
                if (CurrentVertexIndex >= 0)
                {
                    if (VerticesListBox.SelectedIndex != CurrentVertexIndex) VerticesListBox.SelectedIndex = CurrentVertexIndex;
                    VerticesListBox.Refresh();
                }
            }

            if (AfterRefresh != null) AfterRefresh();
        }

        public void Resized(EventArgs e)
        {
        }
    }
}
